package com.ybu.oodd.utils.ai;

import okhttp3.*;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

@Component
public class QwenAIClient {

    @Value("${file.upload-dir}")
    private String uploadDir;

    private static final String systemPrompt = "你是一个极为精准的简历优化助手，你的核心任务是逐字逐句、细致入微地研读用户提供的PDF格式简历，凭借专业且敏锐的洞察力，精准无误地找出其中每一处可优化的地方，并给出精确、具体且高度贴合实际情况的优化建议。在整个处理过程中，需严格遵循以下规则：\n" +
            "- 依据用户输入的语言，以完全相同的语言进行回复，确保沟通的准确性和一致性。\n" +
            "- 优化时，要对项目数据进行精确量化，不能有任何模糊不清的表述。\n" +
            "- 结果集请严格按照JSON格式输出。\n" +
            "- 用户输入的简历文内容在最后。\n" +
            "- “total”代表总共需要修改点的准确个数，“rows”为结果集，“before”是修改前简历上对应的精确原文，“after”是修改后的精准内容，请严格按照以下规范格式写下你的回复。\n" +
            "{\"status\": \"success\",\"total\": 1,\"rows\": [{\"before\": \"修改点原文\",\"after\": \"修改点修改后的文字\"}]}\n" +
            "\n" +
            "回复示例\n" +
            "{\"status\": \"success\",\"total\": 2,\"rows\": [{\"before\": \"实现学生在线多条件查询岗位，标记状态，实现管理员Excel一键导入岗位信息，实现用户反馈、管理员回复功能，单设备登录，邮箱验证码。设计RESTful接口40+个，支持900+并发访问，接口响应时间优化至180ms以内。\",\"after\": \"开发学生端岗位多条件精准查询与状态标记功能，实现管理员岗位信息 Excel 一键导入、用户反馈及管理员回复机制，支持单设备登录与邮箱验证码安全验证；设计 40+RESTful 接口，支撑 900 + 并发访问，将接口响应时间优化至 180ms 内。\"},{\"before\": \"完成整个系统的Mysql Redis数据库设计，Java Vue3代码开发，Apifox接口测试，DockerCompose部署上线\",\"after\": \"完成系统全流程 MySQL 与 Redis 数据库架构设计、Java 后端与 Vue3 前端全栈开发、基于 Apifox 的接口自动化测试及 Docker Compose 容器化部署上线\"}]}";
    private static final String API_KEY = "sk-9feb253da0144a18a55c70c2839a2b6f";
    private static final String DASHSCOPE_API_URL = "https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation";
    private static final OkHttpClient httpClient = new OkHttpClient.Builder()
            .connectTimeout(30, java.util.concurrent.TimeUnit.SECONDS)
            .readTimeout(60, java.util.concurrent.TimeUnit.SECONDS)
            .writeTimeout(30, java.util.concurrent.TimeUnit.SECONDS)
            .build();
    private static final ObjectMapper mapper = new ObjectMapper();

    /**
     * 处理 classpath 下的 PDF 文件（如 resources/templates/xxx.pdf）
     */
    public String AIJL(String resourcePath, String userPrompt) throws IOException {
        String fullPrompt = "";
        if(resourcePath==null) {
            resourcePath = "";
        }
        if(userPrompt==null) {
            userPrompt = "";
        }
        if(resourcePath.isEmpty() && userPrompt.isEmpty()){
            return "{\"status\": \"请上传简历pdf文件或者输入简历内容\"}";
        }
        else if(resourcePath.isEmpty()){
            fullPrompt = systemPrompt + "\n\n--- 简历文件内容如下 ---\n" + userPrompt;
        }else{
            if (!resourcePath.matches("^[a-zA-Z0-9._-]+\\.pdf$")) {
                throw new IllegalArgumentException("非法文件名，仅允许字母、数字、下划线、连字符和 .pdf 扩展名");
            }

            Path filePath = Paths.get(uploadDir, resourcePath);

            // 检查文件是否存在
            if (!Files.exists(filePath)) {
                throw new IOException("PDF 文件未找到: " + filePath);
            }

            // 用 Files.newInputStream 读取文件，得到 InputStream
            try (InputStream inputStream = Files.newInputStream(filePath)) {
                String pdfText = extractTextFromStream(inputStream); // 你的方法，接收 InputStream
                fullPrompt = systemPrompt + "\n\n--- 简历文件内容如下 ---\n" + pdfText;
            }
        }

        // 调用 Qwen 模型
        return callQwenModel(fullPrompt);
    }

    /**
     * 从 InputStream 提取 PDF 文本（PDFBox 3.x 需转为 byte[]）
     */
    private static String extractTextFromStream(InputStream inputStream) throws IOException {
        // 将 InputStream 转为 byte[]
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        int nRead;
        byte[] data = new byte[1024];
        while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
            buffer.write(data, 0, nRead);
        }
        buffer.flush();
        byte[] pdfBytes = buffer.toByteArray();
        inputStream.close();

        // 用 byte[] 加载 PDF
        try (PDDocument document = Loader.loadPDF(pdfBytes)) {
            PDFTextStripper stripper = new PDFTextStripper();
            return stripper.getText(document).trim();
        }
    }

    /**
     * 调用 DashScope Qwen 模型
     */
    private static String callQwenModel(String prompt) throws IOException {
        ObjectNode requestBody = mapper.createObjectNode();
        requestBody.put("model", "qwen-plus");

        ObjectNode input = requestBody.putObject("input");
        input.put("prompt", prompt);

        ObjectNode parameters = requestBody.putObject("parameters");
        parameters.put("max_tokens", 2048);
        parameters.put("temperature", 0.7);

        RequestBody body = RequestBody.create(
                requestBody.toString(),
                MediaType.get("application/json; charset=utf-8")
        );

        Request request = new Request.Builder()
                .url(DASHSCOPE_API_URL)
                .header("Authorization", "Bearer " + API_KEY)
                .header("Content-Type", "application/json")
                .post(body)
                .build();

        try (Response response = httpClient.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                String errorMsg = response.body() != null ? response.body().string() : "No response body";
                throw new IOException("DashScope API error: " + response.code() + " - " + errorMsg);
            }

            String responseBody = response.body().string();
            JsonNode json = mapper.readTree(responseBody);
            JsonNode output = json.get("output");
            if (output != null && output.has("text")) {
                return output.get("text").asText();
            }
            throw new RuntimeException("Unexpected API response: " + responseBody);
        }
    }
}